package naga.x;

import naga.x.common.Config;
import naga.x.common.SimpleUpdater;
import naga.x.common.Updater;
import naga.x.db.DBSessionFactory;
import naga.x.event.EventManager;
import naga.x.net.PacketDispatcher;
import naga.x.service.DefaultServiceManager;
import naga.x.service.ServiceManager;
import naga.x.util.Scheduler;
import naga.x.util.ThreadPool;

/**
 * Hold all of the resources
 * @author yang.li
 *
 */
public class App {
	
	private static final App APP = new App();
	
	protected ServiceManager serviceManager = new DefaultServiceManager();
	protected Config config;
	protected DBSessionFactory dbSessionFactory;
	protected PacketDispatcher packetDispatcher = new PacketDispatcher();
	protected Updater updater = new SimpleUpdater();
	protected EventManager eventManager = new EventManager();
	protected ThreadPool pool = new ThreadPool();
	protected Scheduler schedule = new Scheduler();
	
	private App() {
	}
	
	public static App getApp() {
		return APP;
	}

	public <T extends ServiceManager> T getServiceManager() {
		return (T) serviceManager;
	}

	public <T extends ServiceManager> void setServiceManager(T serviceManager) {
		this.serviceManager = serviceManager;
	}
	
	public <T extends Config> T getConfig() {
		return (T) config;
	}
	
	public <T extends Config> void setConfig(T config) {
		this.config = config;
	}
	
	public DBSessionFactory getDBSessionFactory() {
		return dbSessionFactory;
	}

	public void setDBSessionFactory(DBSessionFactory dbSessionFactory) {
		this.dbSessionFactory = dbSessionFactory;
	}

	public PacketDispatcher getPacketDispatcher() {
		return packetDispatcher;
	}

	public void setPacketDispatcher(PacketDispatcher packetDispatcher) {
		this.packetDispatcher = packetDispatcher;
	}

	public Updater getUpdater() {
		return updater;
	}

	public void setUpdater(Updater updater) {
		this.updater = updater;
	}

	public EventManager getEventManager() {
		return eventManager;
	}

	public ThreadPool getThreadPool() {
		return pool;
	}

	public void setThreadPool(ThreadPool pool) {
		if (this.pool != null) {
			this.pool.shutdown();
		}
		this.pool = pool;
	}

	public Scheduler getSchedule() {
		return schedule;
	}

	public void setSchedule(Scheduler schedule) {
		if (this.schedule != null && !this.schedule.isShutdown()) {
			this.schedule.shutdown();
		}
		this.schedule = schedule;
	}

	public void addShutdownHook(Runnable hook) {
		Runtime.getRuntime().addShutdownHook(new Thread(hook));
	}
	
}
